package com.jzlw.huozhuduan.network.httpservice;

import android.util.Log;

import com.blankj.utilcode.util.SPUtils;

import com.jzlw.huozhuduan.BuildConfig;
import com.jzlw.huozhuduan.appction.MyAPP;
import com.jzlw.huozhuduan.base.SpConfig;
import com.orhanobut.logger.Logger;

import java.io.File;
import java.io.IOException;
import java.net.Proxy;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * ClassName HttpMethods
 * Description HttpMethods
 */
public class HttpMethods {
    public String TAG = "HttpMethods";
    private static final String CACHE_NAME = "平";
    private static String BASE_URL = URLConstant.BASE_URL;
    private static final int DEFAULT_CONNECT_TIMEOUT = 10;
    private static final int DEFAULT_WRITE_TIMEOUT = 10;
    private static final int DEFAULT_READ_TIMEOUT = 10;
    private Retrofit retrofit;
    private HttpApi httpApi;
    /**
     * 请求失败重连次数
     */
    private int RETRY_COUNT = 0;
    private int RE_CONNECT_COUNT = 3;

    private OkHttpClient.Builder okHttpBuilder;

    //构造方法私有
    private HttpMethods() {
        //手动创建一个OkHttpClient并设置超时时间
        okHttpBuilder = new OkHttpClient.Builder();

        /**
         * 设置缓存
         */
        File cacheFile = new File(MyAPP.getContext().getExternalCacheDir(), CACHE_NAME);
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
        Interceptor cacheInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (BuildConfig.DEBUG) {
                    Log.e(TAG, "请求地址==" + request.url().toString());
                }
                if (!NetUtil.isNetworkConnected()) {
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }
                Response response = chain.proceed(request);
                String s = response.headers().get("set-cookie");
                if (!NetUtil.isNetworkConnected()) {
                    int maxAge = 0;
                    // 有网络时 设置缓存超时时间0个小时
                    response.newBuilder()
                            .header("Cache-Control", "public, max-age=" + maxAge)
                            .removeHeader(CACHE_NAME)// 清除头信息，因为服务器如果不支持，会返回一些干扰信息，不清除下面无法生效
                            .build();
                } else {
                    // 无网络时，设置超时为4周
                    int maxStale = 60 * 60 * 24 * 28;
                    response.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                            .removeHeader(CACHE_NAME)
                            .build();
                }
                return response;
            }
        };
        okHttpBuilder.cache(cache).addInterceptor(cacheInterceptor);

        /**
         * 设置头信息
         */
        Interceptor headerInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {

                String token = SPUtils.getInstance().getString(SpConfig.TOKEN);

                Request originalRequest = chain.request();
                Request.Builder requestBuilder = originalRequest.newBuilder()
                        .addHeader("Content-Type", "application/json; charset=utf-8;multipart/form-data")
                        .method(originalRequest.method(), originalRequest.body());
                requestBuilder.addHeader("Authorization", "Bearer " + token);//添加请求头信息，服务器进行token有效性验证
                Response proceed = chain.proceed(requestBuilder.build());
                //                //如果token过期 再去重新请求token 然后设置token的请求头 重新发起请求 用户无感
                /*if (RE_CONNECT_COUNT > 0) {
                    //判定是否失效  2->401 3->402
                    int mType = isTokenExpired(proceed);
                    if (mType == 2) {

                        RE_CONNECT_COUNT--;

                        AutoLoginHolder mAutoLoginHolder = new AutoLoginHolder();
                        String newHeaderToken = mAutoLoginHolder.getNewToken();
                        //使用新的Token，创建新的请求
                        Request newRequest = chain.request().newBuilder()
                                .addHeader("Token", newHeaderToken)
                                .build();
                        return chain.proceed(newRequest);
                    } else if (mType == 3) {
                        //前面402已经消费了 response.body.string ,这里重新new一个
                        Request newRequest = chain.request().newBuilder()
                                .addHeader("Token", token)
                                .build();
                        return chain.proceed(newRequest);
                    }
                }*/

                return proceed;
            }
        };
        okHttpBuilder.addInterceptor(headerInterceptor);

        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    Logger.d(message);
                }


            });
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            //设置 Debug Log 模式
            okHttpBuilder.addInterceptor(loggingInterceptor);
        }


        /**
         * 设置超时和重新连接
         */
        okHttpBuilder.connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS);
        okHttpBuilder.readTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.SECONDS);
        okHttpBuilder.writeTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS);
        //错误重连
        okHttpBuilder.retryOnConnectionFailure(true);
        okHttpBuilder.proxy(Proxy.NO_PROXY); //防止被抓包软件抓。

        retrofit = new Retrofit.Builder()
                .client(okHttpBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())//json转换成JavaBean
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();
        httpApi = retrofit.create(HttpApi.class);
    }

    //在访问HttpMethods时创建单例
    private static class SingletonHolder {
        private static final HttpMethods INSTANCE = new HttpMethods();

    }

    //获取单例
    public static HttpMethods getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 获取retrofit
     *
     * @return
     */
    public Retrofit getRetrofit() {
        return retrofit;
    }

    public void changeBaseUrl(String baseUrl) {
        retrofit = new Retrofit.Builder()
                .client(okHttpBuilder.build())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(baseUrl)
                .build();
        httpApi = retrofit.create(HttpApi.class);
    }

    /**
     * 获取httpService
     *
     * @return
     */
    public HttpApi getHttpApi(/*EncodeJsonBean registInfoEntity*/) {
        //设置sign
        //setSign(registInfoEntity);
        return httpApi;
    }

    /**
     * 设置订阅 和 所在的线程环境
     */
    public <T> void toSubscribe(Observable<T> o, DisposableObserver<T> s) {

        o.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .retry(RETRY_COUNT)//请求失败重连次数
                .subscribe(s);
    }

   /* public void setSign(EncodeJsonBean registInfoEntity) {

        RE_CONNECT_COUNT = 3;

        if (registInfoEntity != null) {
            long nowtime = new Date().getTime();
            long lasttime = PreferencesUtil.getLongPreference(PreferencesKeyConfig.GET_TIME);
            long servertime = PreferencesUtil.getLongPreference(PreferencesKeyConfig.SERVER_TIME);
            long startime = nowtime - lasttime + servertime + 20;
            registInfoEntity.setTimeStamp(startime);

            Object context = registInfoEntity.getContext();
            String json;
            if (context instanceof String) {
                json = context.toString();
            } else {
                //使Gson忽略特殊字符转义
                Gson gson = new GsonBuilder().disableHtmlEscaping().create();
                json = gson.toJson(context);

                *//*if (json.contains("?v\\u003d")) {
                    json = json.replace("\\u003d", "=");
                }
                if (json.contains("\\u003c")) {
                    json = json.replace("\\u003c", "<");
                }
                if (json.contains("\\u003e")) {
                    json = json.replace("\\u003e", ">");
                }*//*
            }
            if (BuildConfig.DEBUG) {
                Log.e(TAG, "上传json: " + json);
            }
            String sign = ToolUtil.GetSign(json,
                    "huaimu@sign", String.valueOf(registInfoEntity.getTimeStamp()));
            registInfoEntity.setSign(sign);
        }
    }*/

    /**
     * 根据Response，判断Token是否失效
     * 401表示token过期
     *
     * @param response
     * @return
     */
    /*private int isTokenExpired(Response response) {
        try {
            if (response.code() == 401) {
                ResponseBody body = response.body();
                String errorBody = body.string();
                if (!TextUtils.isEmpty(errorBody)) {
                    ErrorCodeEntity errorCode = JSONUtils.fromJson(errorBody, ErrorCodeEntity.class);
                    if (errorCode.getCode() == 402) {
                        return 3;
                    }
                }
                return 2;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return 1;
    }*/


}
